home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0992.ARJ / GENBALL.C < prev    next >
Text File  |  1992-04-04  |  10KB  |  295 lines

  1. /* Generates the vertices for a ball approximated with polygonal
  2.    facets, in a form suitable for including into a C module. Vertices,
  3.    faces, and supporting info is generated, in the following format:
  4.  
  5. ----------------------------start------------------------------
  6. #define NUM_FACES <number of faces in object>
  7. #define NUM_VERTS <number of vertices in object>
  8. #define NUM_REAL_VERTS <number of vertices in object, excluding unit normal
  9.       endpoints>
  10.  
  11. Point3 Verts[] = { <vertices in object, with unit normal endpoints coming
  12.       last> };
  13.  
  14. static int Face0[] = { <unit normal endpoint index, followed by vertex
  15.       indexes for face, clockwise> };
  16. static int Face1[] = { <unit normal endpoint index, followed by vertex
  17.       indexes for face, clockwise> };
  18.                   :
  19. static int Face<n>[] = { <unit normal endpoint index, followed by vertex
  20.       indexes for face, clockwise> };
  21.  
  22. static int *VertNumList[] = { <ptr to vertex index list per face> };
  23. static int VertsInFace[] = { <# vertices in each face> };
  24.  
  25. ***Note: the first two vertices in the vertex list for each face are always
  26. the end and start points of a unit normal vector for the face, pointing in
  27. the direction from which the face can be seen; these are used for shading.
  28. The second point is also an active vertex***
  29. ----------------------------end--------------------------------
  30. */
  31.  
  32. #include <stdio.h>
  33. #include <conio.h>
  34. #include <math.h>
  35. #include <string.h>
  36. #include "polygon.h"
  37.  
  38. #define PI  3.14159265358979323846
  39. #define DOUBLE_TO_FIXED(x) ((long) (x * 65536.0 + 0.5))
  40.  
  41. void main(void);
  42. void PrintVertex(struct Point3 *);
  43. void Print4Indexes(int, int, int, int, int);
  44. void Print5Indexes(int, int, int, int, int, int);
  45. void UnitNormal(struct Point3 * Vec, int BaseIndex, int Vec0EndIndex,
  46.    int Vec1EndIndex);
  47.  
  48. /* Used to rotate around the Y axis by one band's width */
  49. static double YXform[4][4] = {
  50.    {1.0, 0.0, 0.0, 0.0},
  51.    {0.0, 1.0, 0.0, 0.0},
  52.    {0.0, 0.0, 1.0, 0.0},
  53.    {0.0, 0.0, 0.0, 1.0}
  54. };
  55.  
  56. /* Used to rotate around the Z axis by one band's width */
  57. static double ZXform[4][4] = {
  58.    {1.0, 0.0, 0.0, 0.0},
  59.    {0.0, 1.0, 0.0, 0.0},
  60.    {0.0, 0.0, 1.0, 0.0},
  61.    {0.0, 0.0, 0.0, 1.0}
  62. };
  63.  
  64. struct Point3 Pointlist[1000];
  65. int NumPoints = 0;
  66.  
  67. static FILE *OutputFile;   /* where we'll write to */
  68.  
  69. int FirstUnitNormalIndex;
  70.  
  71. void main()
  72. {
  73.    int Radius, Bands, i, j, LastIndex, BandsX2, LastBandStartIndex;
  74.    int TopBandStartIndex, BottomBandStartIndex, FaceNum;
  75.    struct Point3 BaseVec, BandVec, WorkingVec, TempVec;
  76.    char OutputFilename[130];
  77.    char Description[130];
  78.  
  79.    printf("Radius: ");
  80.    scanf("%d",&Radius);
  81.    printf("Bands: ");
  82.    scanf("%d",&Bands);
  83.    printf("Output file: ");
  84.    OutputFilename[0] = 127;
  85.    cgets(OutputFilename);
  86.    printf("\nBrief description: ");
  87.    Description[0] = 127;
  88.    cgets(Description);
  89.    printf("\n");
  90.  
  91.    BandsX2 = Bands*2;
  92.  
  93.    if ((OutputFile = fopen(&OutputFilename[2], "w")) == NULL) {
  94.       printf("Error\n");
  95.       exit(1);
  96.    }
  97.  
  98.    /* Descriptive comments */
  99.    fprintf(OutputFile, "/* %s */\n", &Description[2]);
  100.    fprintf(OutputFile, "/* Created with radius = %d, bands = %d */\n",
  101.          Radius, Bands);
  102.  
  103.    /* Defines for # of faces and vertices */
  104.    fprintf(OutputFile, "#define NUM_FACES %d\n", BandsX2*Bands);
  105.    fprintf(OutputFile, "#define NUM_VERTS %d\n\n",
  106.          2+1+BandsX2*(Bands-1)+1+ (BandsX2*Bands));
  107.    /* # of vertices excluding unit normal endpoints */
  108.    fprintf(OutputFile, "#define NUM_REAL_VERTS %d\n\n",
  109.          2+1+BandsX2*(Bands-1)+1);
  110.  
  111.    /* Do the polygon vertices */
  112.    fprintf(OutputFile, "Point3 Verts[] = {\n");
  113.  
  114.     /* Generate the rotation matrices */
  115.    AppendRotationY(YXform, PI / Bands);
  116.    AppendRotationZ(ZXform, PI / Bands);
  117.  
  118.    /* Do the point at the top */
  119.    BaseVec.X = 0.0;
  120.    BaseVec.Y = Radius;
  121.    BaseVec.Z = 0.0;
  122.    BaseVec.W = 1.0;
  123.    PrintVertex(&BaseVec);
  124.  
  125.    BandVec = BaseVec;
  126.  
  127.    /* Do the vertices in each band in turn */
  128.    for (i=1; i<Bands; i++) {
  129.       /* Rotate around Z to the next band's latitude */
  130.       XformVec(ZXform, (double *)&BandVec, (double *)&TempVec);
  131.       WorkingVec = BandVec = TempVec;
  132.         /* Do the vertices in this band */
  133.       for (j=0; j<BandsX2; j++) {
  134.          WorkingVec = TempVec;
  135.          PrintVertex(&WorkingVec);
  136.          /* Now rotate around Y to the next vertex's longitude */
  137.          XformVec(YXform, (double *)&WorkingVec, (double *)&TempVec);
  138.       }
  139.    }
  140.  
  141.    /* Do the point at the bottom */
  142.    BaseVec.Y = -Radius;
  143.    PrintVertex(&BaseVec);
  144.  
  145.    /* Now generate the unit normal endpoint for each face, as the last
  146.       entries in the vertex list */
  147.    /* Index in overall vertex list of first unit normal endpoint we'll
  148.       create; remember where we can find it */
  149.    FirstUnitNormalIndex = NumPoints;
  150.  
  151.    FaceNum = 0;
  152.  
  153.    /* Unit normal endpoints in top band */
  154.    for (i=0; i<BandsX2; i++) {
  155.       UnitNormal(&BaseVec, 0, ((i+1)%BandsX2)+1, i+1);
  156.       PrintVertex(&BaseVec);
  157.       FaceNum++;
  158.    }
  159.  
  160.    /* Unit normal endpoints in middle bands */
  161.    for (j=0; j<(Bands-2); j++) {
  162.       TopBandStartIndex = j*BandsX2 + 1;
  163.       BottomBandStartIndex = (j+1)*BandsX2 + 1;
  164.         /* Indexes in this band */
  165.       for (i=0; i<BandsX2; i++) {
  166.          UnitNormal(&BaseVec, i+TopBandStartIndex,
  167.                ((i+1)%BandsX2)+TopBandStartIndex,
  168.                i+BottomBandStartIndex);
  169.          PrintVertex(&BaseVec);
  170.          FaceNum++;
  171.       }
  172.    }
  173.  
  174.    /* Unit normal endpoints in bottom band */
  175.    LastIndex = BandsX2*(Bands-1)+1;
  176.    LastBandStartIndex = BandsX2*(Bands-2)+1;
  177.    for (i=0; i<BandsX2; i++) {
  178.       UnitNormal(&BaseVec, LastBandStartIndex+i,
  179.             LastBandStartIndex+((i+1)%BandsX2), LastIndex);
  180.       PrintVertex(&BaseVec);
  181.       FaceNum++;
  182.    }
  183.  
  184.    /* Done generating points, including both polygon vertices and unit
  185.       normals */
  186.    fprintf(OutputFile, "};\n\n");
  187.  
  188.  
  189.    /* Do the vertex indexes for each face in each band */
  190.    FaceNum = 0;
  191.  
  192.    /* Vertex indexes in top band, with unit normal endpoint first */
  193.    for (i=0; i<BandsX2; i++) {
  194.       Print4Indexes(FaceNum++, FirstUnitNormalIndex++, 0,
  195.             ((i+1)%BandsX2)+1, i+1);
  196.    }
  197.  
  198.    /* Vertex indexes in middle bands, with unit normal endpoints first */
  199.    for (j=0; j<(Bands-2); j++) {
  200.       TopBandStartIndex = j*BandsX2 + 1;
  201.       BottomBandStartIndex = (j+1)*BandsX2 + 1;
  202.         /* Indexes in this band */
  203.       for (i=0; i<BandsX2; i++) {
  204.          Print5Indexes(FaceNum++, FirstUnitNormalIndex++,
  205.                i+TopBandStartIndex,
  206.                ((i+1)%BandsX2)+TopBandStartIndex,
  207.                ((i+1)%BandsX2)+BottomBandStartIndex,
  208.                i+BottomBandStartIndex);
  209.       }
  210.    }
  211.  
  212.    /* Vertex indexes in bottom band, with unit normal endpoint first */
  213.    LastIndex = BandsX2*(Bands-1)+1;
  214.    LastBandStartIndex = BandsX2*(Bands-2)+1;
  215.    for (i=0; i<BandsX2; i++) {
  216.       Print4Indexes(FaceNum++, FirstUnitNormalIndex++,
  217.             LastBandStartIndex+i,
  218.             LastBandStartIndex+((i+1)%BandsX2), LastIndex);
  219.    }
  220.  
  221.    /* Do the list of pointers to index arrays for each face */
  222.    fprintf(OutputFile, "\nstatic int *VertNumList[] = {\n");
  223.    for (i=0; i<(BandsX2*Bands); i++) {
  224.       fprintf(OutputFile, "Face%d,\n", i);
  225.    }
  226.    fprintf(OutputFile, "};\n");
  227.  
  228.    /* Do the # of vertices in each face (3 for the top and bottom
  229.       bands, 4 for the rest) */
  230.    fprintf(OutputFile, "\nstatic int VertsInFace[] = {\n");
  231.    for (i=0; i<BandsX2; i++) fprintf(OutputFile, "3,\n");
  232.    for (i=0; i<(BandsX2*(Bands-2)); i++) fprintf(OutputFile, "4,\n");
  233.    for (i=0; i<BandsX2; i++) fprintf(OutputFile, "3,\n");
  234.    fprintf(OutputFile, "};\n");
  235.  
  236.    exit(0);
  237. }
  238.  
  239. /* Prints the array of indexes for a 5-vertex face (generally four vertices
  240.    plus the unit normal endpoint, actually). */
  241. void Print5Indexes(int FaceNum, int V1, int V2, int V3, int V4, int V5)
  242. {
  243.       fprintf(OutputFile, "static int Face%d[] = {%d,%d,%d,%d,%d};\n",
  244.             FaceNum, V1, V2, V3, V4, V5);
  245. }
  246.  
  247. /* Prints the array of indexes for a 4-vertex face (generally three vertices
  248.    plus the unit normal endpoint, actually). */
  249. void Print4Indexes(int FaceNum, int V1, int V2, int V3, int V4)
  250. {
  251.       fprintf(OutputFile, "static int Face%d[] = {%d,%d,%d,%d};\n",
  252.             FaceNum, V1, V2, V3, V4);
  253. }
  254.  
  255. /* Prints a vertex, in 16.16 fixed-point form */
  256. void PrintVertex(struct Point3 *Vec)
  257. {
  258.    long X = DOUBLE_TO_FIXED(Vec->X);
  259.    long Y = DOUBLE_TO_FIXED(Vec->Y);
  260.    long Z = DOUBLE_TO_FIXED(Vec->Z);
  261.    Pointlist[NumPoints++] = *Vec; /* remember this point */
  262.  
  263.    fprintf(OutputFile, "{%ld, %ld, %ld},\n", X, Y, Z);
  264. }
  265.  
  266. /* Calculates the end of the unit normal by calculating the cross-product of
  267.    the first and last vectors, and normalizing it to 1 unit in length */
  268. void UnitNormal(struct Point3 * Vec, int BaseIndex, int Vec0EndIndex,
  269.    int Vec1EndIndex)
  270. {
  271.    double v1, v2, v3, w1, w2, w3, Xlen, Ylen, Zlen, Length;
  272.  
  273.    v1 = Pointlist[Vec0EndIndex].X - Pointlist[BaseIndex].X;
  274.    v2 = Pointlist[Vec0EndIndex].Y - Pointlist[BaseIndex].Y;
  275.    v3 = Pointlist[Vec0EndIndex].Z - Pointlist[BaseIndex].Z;
  276.    w1 = Pointlist[Vec1EndIndex].X - Pointlist[BaseIndex].X;
  277.    w2 = Pointlist[Vec1EndIndex].Y - Pointlist[BaseIndex].Y;
  278.    w3 = Pointlist[Vec1EndIndex].Z - Pointlist[BaseIndex].Z;
  279.    /* Calculate perpendicular relative to the BaseIndex point in Vec */
  280.    Vec->X = v2*w3 - v3*w2;
  281.    Vec->Y = v3*w1 - v1*w3;
  282.    Vec->Z = v1*w2 - v2*w1;
  283.    /* Calculate the length of the normal, and reverse its direction so that
  284.       a positive normal points toward the screen, negative points away */
  285.    Xlen = -(Vec->X - Pointlist[BaseIndex].X);
  286.    Ylen = -(Vec->Y - Pointlist[BaseIndex].Y);
  287.    Zlen = -(Vec->Z - Pointlist[BaseIndex].Z);
  288.    Length = sqrt(Xlen*Xlen + Ylen*Ylen + Zlen*Zlen);
  289.    /* Scale it to a unit normal and offset it from the start point */
  290.    Vec->X = Pointlist[BaseIndex].X + (Xlen / Length);
  291.    Vec->Y = Pointlist[BaseIndex].Y + (Ylen / Length);
  292.    Vec->Z = Pointlist[BaseIndex].Z + (Zlen / Length);
  293. }
  294.  
  295.